package com.iacrqq.sedaf.event;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.iacrqq.sedaf.config.Configuration;
import com.iacrqq.sedaf.queue.Input;
import com.iacrqq.sedaf.queue.Queue;
import com.iacrqq.sedaf.queue.exception.QueueFullException;
import com.iacrqq.sedaf.stage.Stage;

/**
 * 
 * Event dispatcher
 * 
 * @author sihai
 * 
 */
public class DefaultEventDispatcher implements EventDispatcher
{

	private static final Log logger = LogFactory.getLog(DefaultEventDispatcher.class);

	private String name;
	private Map<Integer, Stage> routerTable = new HashMap<Integer, Stage>();

	@Override
	public void setName(String name)
	{
		this.name = name;
	}

	@Override
	public String getName()
	{
		return this.name;
	}

	@Override
	public void registerRouterEntry(int state, Stage stage)
	{
		routerTable.put(state, stage);
	}

	@Override
	public void init(Configuration config) throws Exception
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void destroy() throws Exception
	{
		routerTable.clear();
	}

	@Override
	public void dispatch(Event event)
	{

		Stage stage = routerTable.get(event.getState());

		if (stage != null)
		{
			Input<Event> input = stage.getInput();

			if (input != null)
			{
				while(true)
				{
					try
					{
						((Queue)input).enqueue(event);
						break;
					}
					catch(QueueFullException e)
					{
						logger.error(e);
						
						try
						{
							Thread.sleep(100);
						}
						catch(InterruptedException ex)
						{
							Thread.currentThread().interrupt();
							logger.error(ex);
						}
						continue;
					}
				}
				logger.info(new StringBuilder("EventDispatcher:").append(name).append(" dispatch one event={state:").append(event.getState()).append("}").append(" to stage={name:").append(stage.getName()).append("}").toString());
			}
			else
			{
				logger.error(new StringBuilder(
						"Wrong stage found for the event, the stage has none input, event.state=").append(
						event.getState()).toString());
			}
		}
		else
		{
			logger.error(new StringBuilder("None stage found for the event, event.state=").append(event.getState())
					.toString());
		}
	}

	@Override
	public void dispatch(Event[] events)
	{
		for (Event event : events)
		{
			dispatch(event);
		}
	}

}
